package dashboard

import (
	// We're not using it for security stuff, so it's fine.
	//nolint:gosec
	
	
	

	
	
	
	
	
	
	
	
	
)

// TagAnnotation describes an annotation represented as a Tag.
// See https://grafana.com/docs/grafana/latest/reference/annotations/#query-by-tag
type TagAnnotation struct {
	Name       string
	Datasource string
	IconColor  string   `yaml:"color"`
	Tags       []string `yaml:",flow"`
}

// Option represents an option that can be used to configure a
// dashboard.
type Option func(dashboard *Builder) error

// TimezoneOption represents a possible value for the dashboard's timezone
// configuration.
type TimezoneOption string

// DefaultTimezone sets the dashboard's timezone to the default one used by
// Grafana.
const DefaultTimezone TimezoneOption = ""

// UTC sets the dashboard's timezone to UTC.
const UTC TimezoneOption = "utc"

// Browser sets the dashboard's timezone to the browser's one.
const Browser TimezoneOption = "browser"

// Builder is the main builder used to configure dashboards.
type Builder struct {
	board  *sdk.Board
	alerts []*alert.Alert
}

// New creates a new dashboard builder.
func ( string,  ...Option) (Builder, error) {
	 := sdk.NewBoard()
	.ID = 0

	 := &Builder{board: }

	for ,  := range append(defaults(), ...) {
		if  := ();  != nil {
			return *, 
		}
	}

	return *, nil
}

func defaults() []Option {
	return []Option{
		defaultTimePicker(),
		Timezone(DefaultTimezone),
		Time("now-3h", "now"),
		SharedCrossHair(),
	}
}

func defaultTimePicker() Option {
	return func( *Builder) error {
		.board.Timepicker = sdk.Timepicker{
			RefreshIntervals: []string{"5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"},
			TimeOptions:      []string{"5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"},
		}

		return nil
	}
}

// MarshalJSON implements the encoding/json.Marshaler interface.
//
// This method can be used to render the dashboard as JSON
// which your configuration management tool of choice can then feed into
// Grafana's dashboard via its provisioning support.
// See https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards
func ( *Builder) () ([]byte, error) {
	return json.Marshal(.board)
}

// MarshalIndentJSON renders the dashboard as indented JSON
// which your configuration management tool of choice can then feed into
// Grafana's dashboard via its provisioning support.
// See https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards
func ( *Builder) () ([]byte, error) {
	return json.MarshalIndent(.board, "", "  ")
}

// Alerts returns all the alerts defined in this dashboard.
func ( *Builder) () []*alert.Alert {
	return .alerts
}

// Internal.
func ( *Builder) () *sdk.Board {
	return .board
}

// VariableAsConst adds a templated variable, defined as a set of constant
// values.
// See https://grafana.com/docs/grafana/latest/reference/templating/#variable-types
func ( string,  ...constant.Option) Option {
	return func( *Builder) error {
		 := constant.New(, ...)

		.board.Templating.List = append(.board.Templating.List, .Builder)

		return nil
	}
}

// ID sets the ID used by the dashboard.
func ( uint) Option {
	return func( *Builder) error {
		.board.ID = 

		return nil
	}
}

// UID sets the UID used by the dashboard.
func ( string) Option {
	return func( *Builder) error {
		 := 

		if len() > 40 {
			// We're not using it for security stuff, so it's fine.
			//nolint:gosec
			 := sha1.Sum([]byte())
			 = hex.EncodeToString([:])
		}

		.board.UID = 

		return nil
	}
}

// Slug sets the Slug used by the dashboard.
func ( string) Option {
	return func( *Builder) error {
		.board.Slug = 

		return nil
	}
}

// VariableAsCustom adds a templated variable, defined as a set of custom
// values.
// See https://grafana.com/docs/grafana/latest/reference/templating/#variable-types
func ( string,  ...custom.Option) Option {
	return func( *Builder) error {
		 := custom.New(, ...)

		.board.Templating.List = append(.board.Templating.List, .Builder)

		return nil
	}
}

// VariableAsInterval adds a templated variable, defined as an interval.
// See https://grafana.com/docs/grafana/latest/reference/templating/#variable-types
func ( string,  ...interval.Option) Option {
	return func( *Builder) error {
		 := interval.New(, ...)

		.board.Templating.List = append(.board.Templating.List, .Builder)

		return nil
	}
}

// VariableAsQuery adds a templated variable, defined as a query.
// See https://grafana.com/docs/grafana/latest/reference/templating/#variable-types
func ( string,  ...query.Option) Option {
	return func( *Builder) error {
		 := query.New(, ...)

		.board.Templating.List = append(.board.Templating.List, .Builder)

		return nil
	}
}

// VariableAsDatasource adds a templated variable, defined as a datasource.
// See https://grafana.com/docs/grafana/latest/variables/variable-types/add-data-source-variable/
func ( string,  ...datasource.Option) Option {
	return func( *Builder) error {
		 := datasource.New(, ...)

		.board.Templating.List = append(.board.Templating.List, .Builder)

		return nil
	}
}

// VariableAsText adds a templated variable, defined as a free text input.
// See https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#add-a-text-box-variable
func ( string,  ...text.Option) Option {
	return func( *Builder) error {
		 := text.New(, ...)

		.board.Templating.List = append(.board.Templating.List, .Builder)

		return nil
	}
}

// ExternalLinks adds a dashboard-level external links.
// See https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/manage-dashboard-links/#add-a-url-link-to-a-dashboard
func ( ...ExternalLink) Option {
	return func( *Builder) error {
		for ,  := range  {
			.board.Links = append(.board.Links, .asSdk())
		}

		return nil
	}
}

// DashboardLinks adds a dashboard-level links to other dashboards.
// See https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/manage-dashboard-links/#dashboard-links
func ( ...DashboardLink) Option { //nolint:revive
	return func( *Builder) error {
		for ,  := range  {
			.board.Links = append(.board.Links, .asSdk())
		}

		return nil
	}
}

// Row adds a row to the dashboard.
func ( string,  ...row.Option) Option {
	return func( *Builder) error {
		,  := row.New(.board, , ...)
		if  != nil {
			return 
		}

		.alerts = append(.alerts, .Alerts()...)

		return nil
	}
}

// TagsAnnotation adds a new source of annotation for the dashboard.
func ( TagAnnotation) Option {
	return func( *Builder) error {
		.board.Annotations.List = append(.board.Annotations.List, sdk.Annotation{
			Name:       .Name,
			Datasource: &sdk.DatasourceRef{LegacyName: .Datasource},
			IconColor:  .IconColor,
			Enable:     true,
			Tags:       .Tags,
			Type:       "tags",
		})

		return nil
	}
}

// Editable marks the dashboard as editable.
func () Option {
	return func( *Builder) error {
		.board.Editable = true

		return nil
	}
}

// ReadOnly marks the dashboard as non-editable.
func () Option {
	return func( *Builder) error {
		.board.Editable = false

		return nil
	}
}

// SharedCrossHair configures the graph tooltip to be shared across panels.
func () Option {
	return func( *Builder) error {
		.board.SharedCrosshair = true

		return nil
	}
}

// DefaultTooltip configures the graph tooltip NOT to be shared across panels.
func () Option {
	return func( *Builder) error {
		.board.SharedCrosshair = false

		return nil
	}
}

// Tags adds the given set of tags to the dashboard.
func ( []string) Option {
	return func( *Builder) error {
		.board.Tags = 

		return nil
	}
}

// AutoRefresh defines the auto-refresh interval for the dashboard.
func ( string) Option {
	return func( *Builder) error {
		.board.Refresh = &sdk.BoolString{Flag: true, Value: }

		return nil
	}
}

// Time defines the default time range for the dashboard, e.g. from "now-6h" to
// "now".
func (,  string) Option {
	return func( *Builder) error {
		.board.Time = sdk.Time{From: , To: }

		return nil
	}
}

// Timezone defines the default timezone for the dashboard, e.g. "utc".
func ( TimezoneOption) Option {
	return func( *Builder) error {
		.board.Timezone = string()

		return nil
	}
}